﻿//------------------------------------------------------------
// AureFramework
// Developed By Drunk Fish
// GitHub: https://github.com/YYYurz
// Gitee: https://gitee.com/yyyurz
//------------------------------------------------------------

using System;
using UnityEngine;

namespace AureFramework.Entity
{
	public sealed partial class EntityModule : AureFrameworkModule, IEntityModule
	{
		private int entityIdAccumulator;
		
		[SerializeField]private EntityGroup[] entityGroupArray;

		/// <summary>
		/// 模块初始化，只在第一次被获取时调用一次
		/// </summary>
		public override void Init()
		{
			foreach (var entityGroup in entityGroupArray)
			{
				var groupGameObject = new GameObject($"Group - {entityGroup.Name}");
				groupGameObject.transform.SetParent(transform);
				groupGameObject.transform.localPosition = Vector3.zero;
				entityGroup.Init(groupGameObject);
			}
		}

		/// <summary>
		/// 框架轮询
		/// </summary>
		/// <param name="elapseTime"> 距离上一帧的流逝时间，秒单位 </param>
		/// <param name="realElapseTime"> 距离上一帧的真实流逝时间，秒单位 </param>
		public override void Tick(float elapseTime, float realElapseTime)
		{
			foreach (var entityGroup in entityGroupArray)
			{
				entityGroup.Update(elapseTime, realElapseTime);
			}
		}

		/// <summary>
		/// 框架物理轮询
		/// </summary>
		/// <param name="fixedElapseTime"></param>
		/// <param name="realFixedElapseTime"></param>
		public override void FixedTick(float fixedElapseTime, float realFixedElapseTime)
		{
			foreach (var entityGroup in entityGroupArray)
			{
				entityGroup.FixedUpdate(fixedElapseTime, realFixedElapseTime);
			}
		}

		/// <summary>
		/// 框架清理
		/// </summary>
		public override void Clear()
		{
			HideAllEntities();
		}

		/// <summary>
		/// 获取实体组
		/// </summary>
		/// <param name="groupName">实体组名称</param>
		/// <returns></returns>
		public IEntityGroup GetEntityGroup(string groupName)
		{
			if (string.IsNullOrEmpty(groupName))
			{
				Debug.LogError("Entity group name is invalid.");
				return null;
			}

			foreach (var entityGroup in entityGroupArray)
			{
				if (entityGroup.Name == groupName)
				{
					return entityGroup;
				}
			}

			return null;
		}

		/// <summary>
		/// 获取所有实体组
		/// </summary>
		/// <returns></returns>
		public IEntityGroup[] GetAllEntityGroups()
		{
			var result = new IEntityGroup[entityGroupArray.Length];
			for (var i = 0; i < entityGroupArray.Length; i++)
			{
				result[i] = entityGroupArray[i];
			}
			
			return result;
		}

		/// <summary>
		/// 获取实体
		/// </summary>
		/// <param name="entityId">实体Id</param>
		/// <returns></returns>
		public EntityLogic GetEntity(int entityId)
		{
			foreach (var entityGroup in entityGroupArray)	
			{
				var result = entityGroup.GetEntity(entityId);
				if (result != null)
				{
					return result;
				}
			}

			return null;
		}
		
		/// <summary>
		/// 预加载实体
		/// </summary>
		/// <param name="entityAssetName"></param>
		/// <param name="groupName"></param>
		/// <param name="callback"></param>
		public void PreloadEntity<T>(string entityAssetName, string groupName, Action<bool> callback = null)
		{
			PreloadEntity(typeof(T), entityAssetName, groupName, callback);
		}

		/// <summary>
		/// 预加载实体
		/// </summary>
		/// <param name="entityLogicType"></param>
		/// <param name="entityAssetName"></param>
		/// <param name="groupName"></param>
		/// <param name="callback"></param>
		public void PreloadEntity(Type entityLogicType, string entityAssetName, string groupName, Action<bool> callback)
		{
			if (string.IsNullOrEmpty(entityAssetName))
			{
				Debug.LogError("Entity asset name is invalid.");
				return;
			}
			
			if (!entityLogicType.IsClass)
			{
				Debug.LogError("Logic type must be class.");
				return;
			}
			
			if (!entityLogicType.IsSubclassOf(typeof(EntityLogic)))
			{
				Debug.LogError("Logic type must be subclass of EntityLogic.");
				return;
			}

			var entityGroup = (EntityGroup)GetEntityGroup(groupName);
			if (entityGroup == null)
			{
				Debug.LogError($"Entity group is not exist. Entity group name :{groupName}");
				return;
			}

			var entityId = GetEntityId();
			entityGroup.PreloadEntity(entityLogicType, entityId, entityAssetName, callback);
		}

		/// <summary>
		/// 显示实体
		/// </summary>
		/// <param name="entityAssetName">实体资源名称</param>
		/// <param name="groupName">实体组名称</param>
		/// <param name="userData">用户自定义数据</param>
		/// <returns></returns>
		public int ShowEntity<T>(string entityAssetName, string groupName, object userData)
		{
			return ShowEntity(typeof(T), entityAssetName, groupName, userData);
		}

		/// <summary>
		/// 显示实体
		/// </summary>
		/// <param name="entityLogicType">实体逻辑类</param>
		/// <param name="entityAssetName">实体资源名称</param>
		/// <param name="groupName">实体组名称</param>
		/// <param name="userData">用户自定义数据</param>
		/// <returns></returns>
		public int ShowEntity(Type entityLogicType, string entityAssetName, string groupName, object userData = null)
		{
			if (string.IsNullOrEmpty(entityAssetName))
			{
				Debug.LogError("Entity asset name is invalid.");
				return 0;
			}
			
			if (!entityLogicType.IsClass)
			{
				Debug.LogError("Logic type must be class.");
				return 0;
			}
			
			if (!entityLogicType.IsSubclassOf(typeof(EntityLogic)))
			{
				Debug.LogError("Logic type must be subclass of EntityLogic.");
				return 0;
			}

			var entityGroup = (EntityGroup)GetEntityGroup(groupName);
			if (entityGroup == null)
			{
				Debug.LogError($"Entity group is not exist. Entity group name :{groupName}");
				return 0;
			}

			var entityId = GetEntityId();
			entityGroup.ShowEntity(entityLogicType, entityId, entityAssetName, userData);

			return entityId;
		}

		/// <summary>
		/// 隐藏实体
		/// </summary>
		/// <param name="entityLogic">实体</param>
		public void HideEntity(EntityLogic entityLogic)
		{
			if (entityLogic == null)
			{
				Debug.LogError("Entity is invalid.");
				return;
			}
			
			foreach (var entityGroup in entityGroupArray)
			{
				if (entityGroup.HideEntity(entityLogic))
				{
					return;
				}
			}
			
			Debug.LogWarning($"Entity does not exist, entity Id :{entityLogic.Id}.");
		}
		
		/// <summary>
		/// 隐藏实体
		/// </summary>
		/// <param name="entityId">实体Id</param>
		public void HideEntity(int entityId)
		{
			foreach (var entityGroup in entityGroupArray)
			{
				if (entityGroup.HideEntity(entityId))
				{
					return;
				}
			}
			
			Debug.LogWarning($"Entity does not exist, entity Id :{entityId}.");
		}

		/// <summary>
		/// 隐藏所有实体
		/// </summary>
		public void HideAllEntities()
		{
			foreach (var entityGroup in entityGroupArray)
			{
				entityGroup.HideAllEntities();
			}
		}

		private int GetEntityId()
		{
			while (true)
			{
				++entityIdAccumulator;
				if (entityIdAccumulator == int.MaxValue)
				{
					entityIdAccumulator = 1;
				}

				return entityIdAccumulator;
			}
		}
	}
}